/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 actor_model.h

	$Header: /heroes4/actor_model.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ACTOR_MODEL_H_INCLUDED )
#define ACTOR_MODEL_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <string>

#include "abstract_bitmap_typedef.h"
#include "actor_sequence_ptr.h"
#include "direction.h"
#include "owned_ptr.h"

template < typename type >
class t_abstract_cache;
template < typename t_definition >
class t_actor_model_impl;
class t_actor_sequence;
class  t_bitmap_layer;
struct t_screen_point;
struct t_screen_rect;

// ------------------------------------------------------------------------------
// t_actor_model class template
// ------------------------------------------------------------------------------
class t_actor_model_base
{
public:
	virtual ~t_actor_model_base();
	virtual t_actor_sequence_cache get_cache( std::string const&	name,
											  t_screen_point const& offset ) const = 0;
};

template < typename t_definition_arg >
class t_actor_model : public t_actor_model_base
{
public:
	// Types
	typedef t_definition_arg						t_definition;
	typedef t_cached_ptr<t_definition_arg>          t_definition_ptr;
	typedef typename t_definition_arg::t_action_id	t_action_id;

	// Static data
	enum { k_action_count = t_definition_arg::k_action_count };
	enum { k_cell_width = t_definition_arg::k_cell_width };
	enum { k_cell_height = t_definition_arg::k_cell_height };

	// Constructors/Destructor
	explicit t_actor_model( t_definition_ptr definition_ptr );

	// Member functions
	void					draw_to( t_action_id			action_id,
									 t_direction			direction,
									 int					frame_num,
									 t_screen_rect const&	source_rect,
									 t_abstract_bitmap16&	dest,
									 t_screen_point const&	dest_point,
									 int                    alpha = 15 ) const;
	void					draw_to( t_action_id			action_id,
									 t_direction			direction,
									 int					frame_num,
									 t_abstract_bitmap16&	dest,
									 t_screen_point const&	dest_point,
									 int                    alpha = 15  ) const;
	void					draw_to( t_bitmap_layer const*	image,
									 t_screen_rect const&	source_rect,
									 t_abstract_bitmap16&	dest,
									 t_screen_point const&	dest_point,
									 int                    alpha = 15 ) const;
	void					draw_to( t_bitmap_layer const*	image,
									 t_abstract_bitmap16&	dest,
									 t_screen_point const&	dest_point,
									 int                    alpha = 15  ) const;
	void					draw_shadow_to(
								t_action_id				action_id,
								t_direction				direction,
								int						frame_num,
								t_screen_rect const &	source_rect,
								t_abstract_bitmap16 &	dest,
								t_screen_point const &	dest_point,
								int                     alpha = 15  ) const;
	void					draw_shadow_to(
								t_action_id				action_id,
								t_direction				direction,
								int						frame_num,
								t_abstract_bitmap16 &	dest,
								t_screen_point const &	dest_point,
								int                     alpha = 15  ) const;
	t_definition const &	get_definition() const;
	int						get_footprint_size() const;
	int						get_frames_per_second( t_action_id action_id ) const;
	int						get_frame_count( t_action_id action_id, t_direction direction ) const;
	t_screen_point			get_offset( t_action_id action_id, t_direction direction ) const;
	t_screen_rect			get_rect( t_action_id action_id, t_direction direction ) const;
	t_screen_rect			get_rect(
								t_action_id	action_id,
								t_direction	direction,
								int			frame_num ) const;
	t_actor_sequence_cache	get_sequence_cache( t_action_id action_id, 
		                                        t_direction direction ) const;
	t_screen_rect			get_shadow_rect(
								t_action_id	action_id,
								t_direction	direction ) const;
	t_screen_rect			get_shadow_rect(
								t_action_id	action_id,
								t_direction	direction, 
								int			frame_num ) const;
	bool					has_action( t_action_id action_id, t_direction direction ) const;
	bool					hit_test(
								t_action_id				action_id,
								t_direction				direction,
								int						frame_num,
								t_screen_point const &	point ) const;

protected:
	virtual t_actor_sequence_ptr get_sequence_ptr( t_action_id action_id, 
											       t_direction direction ) const;
	// Member functions
private:
	t_screen_point	adjust_incoming( t_screen_point const & point ) const;
	t_screen_rect	adjust_incoming( t_screen_rect const & rect ) const;
	t_screen_point	adjust_outgoing( t_screen_point const & point ) const;
	t_screen_rect	adjust_outgoing( t_screen_rect const & rect ) const;

	// Data members
	mutable t_actor_sequence_cache	m_caches[k_action_count][k_direction_count];
	t_definition_ptr				m_definition_ptr;
};



#endif // !defined( ACTOR_MODEL_H_INCLUDED )
